package se.gala.core;

import java.util.Vector;

import se.gala.core.abstracts.AbstractDrawSymbol;
import se.gala.rng.RNG;
import se.gala.utils.Coordinate2D;
import se.gala.utils.GGObject;

public abstract class M3GMatrix extends GGObject {
	
	protected AbstractDrawSymbol[] swappedLast;

	/**
	 * A table (2-dimensional array) with the gems.
	 */
	protected AbstractDrawSymbol[][] matrix;

	/**
	 * Swaps two symbols by a {@link M3GMove}. There's no check if the move is legal.
	 * This method is a proxy to {@link #swapSymbols(Coordinate2D, Coordinate2D)}
	 * @param mv The swap move.
	 */
	final public void swapSymbols(M3GMove mv) {
		swapSymbols(mv.loc1, mv.loc2);
	}
	
	final public void resetSwappedLast() {
		swappedLast[0] = null;
		swappedLast[1] = null;
	}
	
	final public int swappedLastContains(Vector<AbstractDrawSymbol> v) {
		if (swappedLast[0] != null && v.contains(swappedLast[0])) {
			return v.indexOf(swappedLast[0]);
		} else if (swappedLast[1] != null && v.contains(swappedLast[1])) {
			return v.indexOf(swappedLast[1]);
		} else {
			return -1;
		}
	}

	/**
	 * Swaps two symbols. There's no check if the move is legal.
	 * @param loc1 The location of the first gem.
	 * @param loc2 The location of the second gem.
	 */
	public abstract void swapSymbols(Coordinate2D loc1, Coordinate2D loc2);

	/**
	 * Returns an element in the current M3GMatrix instance.
	 * @param c The location (coordinate) of the symbol in the matrix.
	 * @return The {@link QuetzalSymbol} found at the specified location.
	 */
	final public AbstractDrawSymbol getElementAt(Coordinate2D c) {
		return getElementAt(c.x, c.y, this);
	}

	final public static AbstractDrawSymbol getElementAt(int x, int y, M3GMatrix mx) {
		return mx.matrix[x][y];
	}

	final public static void setElementAt(AbstractDrawSymbol s, int x, int y, M3GMatrix mx) {
		s.setCoordinate(new Coordinate2D(x, y));
		mx.matrix[x][y] = s;
	}
	
	protected abstract AbstractDrawSymbol[] getLinearShuffledGemMatrixCopy(RNG rng);
	
	final public synchronized AbstractDrawSymbol[] removeElementFromLinearMatrix(AbstractDrawSymbol[] lm, AbstractDrawSymbol s) {
		final AbstractDrawSymbol[] newlm = new AbstractDrawSymbol[lm.length - 1];
		boolean found = false;
		int i = 0;
		for (; i < lm.length; i++) {
			if (!found && s == lm[i]) {
				found = true;
			} else {
				if (found) {
					newlm[i - 1] = lm[i];
				} else {
					newlm[i] = lm[i];
				}
			}
		}
		return newlm;
	}

}
